// 韩信点兵：
// 韩信有一队兵，他想知道有多少人，便让士兵排队报数。按从1至m1报数，最末一个士兵报的数为x1；按从1至m2报数，最末一个士兵报的数为x2；按从1至m3报数，最末一个士兵报的数为x3；……,按从1至mn报数，最末一个士兵报的数为xn。
// 请输出最少的人数。
// 输入：第一行为n
//       第二行到第n+1行依次为本次报数的数量和最后1个士兵报的数
// 输出：满足条件的最少人数。
// 输入非法数据时输出error
// 例如：输入：
// 4
// 5 1
// 6 5
// 7 4
// 11 10
// 输出：2111

#include <stdio.h>

int main()
{
    //获取数据
    int n = 0;
    scanf("%d", &n);
    //数据验证
    if(n <= 0)
    {
        printf("error");
        return 0;
    }
    int test[10][2] = {};  //图方便，赌n<11（也可以用malloc动态内存分配）
    for (int i = 0; i < n; i++)
    {
        scanf("%d %d", &test[i][0], &test[i][1]);
        //数据验证
        if(test[i][0] * test[i][1] <= 0 || test[i][0] <= 0)
        {
            printf("error");
            return 0;
        }
        //避免输入如5 5，验证时候使用i % 5 = 0 ！= 5的错误情况（不加这个码图也能过）
        if(test[i][0] == test[i][1])
        {
            test[i][1] = 0;
        }
    }
    //求解
    int isWrong = 0;  //因为未知测试组数，保证每一组都要满足，如果有任何一组不满足，就把isWrong标记为1，继续验证下一个数据
    for (int i = test[0][1]; i < 10000;i += test[0][0])  //假定最多人数穷举到10000人，避免死循环。生成满足第一个条件的数据进行验证，比i++效率高一些（这步还能再优化）
    {
        isWrong = 0;  //初始化isWrong，因为是对每一个测试数据独立的
        //逐个条件验证（跳过第一个条件）
        for (int j = 1; j < n; j++)
        {
            if(i % test[j][0] != test[j][1])
            {
                isWrong = 1;  //如果不满足，isWrong为1，并跳出本循环
                break;
            }
        }
        if(!isWrong)  //如果isWrong==0则运行，代表数据通过所有条件验证
        {
            printf("%d", i);
            return 0;
        }
    }
    printf("No solution");  //运行到最后都没有找到目标数据，输出无解
    return 0;
}

//提交记录
// 276
// 韩信点兵
// C++
// 2024-10-19 00:09:09.0
// score
// 100

//Written By Sibei